
#ifndef ASSEMBLER_INTERPRETER_
#define ASSEMBLER_INTERPRETER_

#include "command.h"
#include "machine_state.h"

namespace assembler {

class InterpreterException {
public:
  virtual const char *error() = 0;
};

class InterpreterArithmeticException : public InterpreterException {
public:
  virtual const char *error() {
    return "Error in arithmetic calculation";
  }
};

class InterpreterNotSupportedCommandException : public InterpreterException {
public:
  virtual const char *error() {
    return "Command not supported";
  }
};

class InterpreterFunctionNotSupportedException : public InterpreterException {
public:
  virtual const char *error() {
    return "Function not supported";
  }
};

// class Interpreter changes machine state according to next command.
// It's Interpret() method expect the command to be completely valid and
// veryfied.
// This class's behaviour is not specified for the case of invalid command
// object.
//
// For CALL command, Interpreter implements some standard mathematical functions.
// RET is not supported (see InterpreterNotSupportedCommandException).
//
// For runtime errors, see InterpreterException subclasses. 
class Interpreter {
public:
  Interpreter(MachineState *state);

  void Interpret(const Command &cmd);

  // Possible arithmetic functions: sin, cos, ln, exp.
  // All arithmetic functions operate over register F0.
  static const int ArithmeticFunctionCount = 4;
  static const char *ArithmeticFunctionNames[ArithmeticFunctionCount];

private:
  static double (*ArithmeticFunctionImpl[ArithmeticFunctionCount])(double);

  static double CallArithmetic(const CommandArgument &function_arg, double x);

  // For register and constant arguments, return value.
  double ArgumentValue(const CommandArgument &arg) const;

  MachineState *state_;
};

}  // namespace assembler

#endif